package cn.tianyigps.tianyigpsyndistributetask.handler;

import cn.tianyigps.tianyigpspublic.bean.EquipmentConfig;
import cn.tianyigps.tianyigpspublic.param.bo.Task;
import cn.tianyigps.tianyigpspublic.param.constant.EquipmentReceiveConstant;
import cn.tianyigps.tianyigpsyndistributetask.dao.DistributeTaskDao;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: WEI.YUAN
 * @Descirption:
 * @Date: 2019/4/27_11:01
 */
@Component
@Slf4j
public class SubscriberHandler {

    private static ObjectMapper OM = new ObjectMapper();
    @Autowired
    DistributeTaskDao distributeTaskDao;

    @Autowired
    HandTaskHandler handTaskHandler;


    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }

    /**
     * 校检规则分发服务
     * @param task
     */
    public void checkData(Task task) {
        //轨迹数据
        Map<String, String> params = task.getParams();

        //根据设备id取出对应的规则配置
        String euipmentId = task.getParams().get(EquipmentReceiveConstant.DeviceCode);
        List<Map<String, Object>> equipmentSubscriberBoMap = getEquipmentConfig(euipmentId);

        if(CollectionUtils.isEmpty(equipmentSubscriberBoMap)){
            log.error("该设备不存在对应订阅规则");
            return ;
        }
        //校检规则
        equipmentSubscriberBoMap.forEach((key) -> {
            if (key.containsKey("keys") && key.get("keys") != null) {
                Map<String, Object> keys = (HashMap) key.get("keys");

                for (Map.Entry<String, Object> entry : keys.entrySet()) {
                    //当规则不是变化时返回
                    if (!"change".equals(((List) entry.getValue()).get(0))) {
                        return;
                    }
                    //当轨迹数据包含状态参数并且不为空时则下发任务
                    if (params.containsKey(entry.getKey()) && !StringUtils.isEmpty(params.get(entry.getKey()))) {

                        String keyString = entry.getKey();
                        Object objectTask = key.get("task");
                        //经纬度改变时只推送一次（默认纬度改变推送）
                        if(keyString.equals(EquipmentReceiveConstant.Longitude)){
                            continue;
                        }
                        Task jsonTask = infoTask(keyString, objectTask, params);
                        //下发任务
                        handTaskHandler.distributeTask(jsonTask);
                    }
                }
            }
        });
    }

    /**
     * 根据id取出配置中的订阅
     * @param euipmentId
     * @return
     */
    public List<Map<String, Object>> getEquipmentConfig(String euipmentId){
        EquipmentConfig equipmentConfig = distributeTaskDao.getEquipmentConfigById(euipmentId);

        //当规则为空时返回
        if (equipmentConfig == null) {
            log.error("不存在对应设备的规则");
            return null;
        }
        List<Map<String, Object>> equipmentSubscriberBoMap = new ArrayList<>();
        try {
            String json = OM.writeValueAsString(equipmentConfig.getSubscriber());
            JavaType javaType = getCollectionType(ArrayList.class, HashMap.class);
            equipmentSubscriberBoMap = OM.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return equipmentSubscriberBoMap;
    }

    /**
     * 包装task
     *
     * @param key
     * @param object
     * @param dataMap
     * @return
     */
    public Task infoTask(String key, Object object, Map<String, String> dataMap) {
        Task task = null;
        try {
            String json = OM.writeValueAsString(object);
            task = OM.readValue(json, Task.class);
            Map<String, String> newMap = task.getParams();

            if (key.equals(EquipmentReceiveConstant.Latitude)) {
                //当是经纬度发生改变时
                newMap.put(EquipmentReceiveConstant.Longitude, dataMap.get(EquipmentReceiveConstant.Longitude));
                newMap.put(EquipmentReceiveConstant.Latitude, dataMap.get(EquipmentReceiveConstant.Latitude));
            }else{
                //非经纬度变化时
                newMap.put(key,dataMap.get(key));
            }
            newMap.put(EquipmentReceiveConstant.DeviceCode, dataMap.get(EquipmentReceiveConstant.DeviceCode));
            task.setParams(newMap);

        } catch (Exception e) {
            e.printStackTrace();
            log.error("task序列化异常:{}", e);
            return null;
        }
        return task;
    }


}
